// %nameParser.c
// LMNO parser generator template
//
// Copyright ©2010-2011 Brigham Toskin.
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
// Some portions of the Software are taken from the Public Domain.
// Based on Lemon v1.
//
////////////////////////////////////////////////////////////////////////////////
//
// This file was generated by LMNO for the %name parser.
// All user-supplied content is the property of its respective authors and is
// subject to the following copyright and licensing terms:
%%
////////////////////////////////////////////////////////////////////////////////


#include "%nameParser.h"


/* Next are that tables used to determine what action to take based on the
 * current state and lookahead token.  These tables are used to implement
 * functions that take a state number and lookahead value and return an
 * action integer.  
 *
 * Suppose the action integer is N.  Then the action is determined as
 * follows
 *
 *   0  < = N  <  YYNSTATE					Shift N.  That is, push the lookahead
 *											token onto the stack and goto state N.
 *
 *   YYNSTATE  < = N  <  YYNSTATE+YYNRULE	Reduce by rule N-YYNSTATE.
 *
 *   N  ==  YYNSTATE+YYNRULE				A syntax error has occurred.
 *
 *   N  ==  YYNSTATE+YYNRULE+1				The parser accepts its input.
 *
 *   N  ==  YYNSTATE+YYNRULE+2				No such action.  Denotes unused
 *											slots in the yy_action[] table.
 *
 * The action table is constructed as a single large table named yy_action[].
 * Given state S and lookahead X, the action is computed as
 *
 *	  yy_action[ yy_shift_ofst[S] + X ]
 *
 * If the index value yy_shift_ofst[S]+X is out of range or if the value
 * yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
 * is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
 * and that yy_default[S] should be used instead.  
 *
 * The formula above is for computing the action when the lookahead is
 * a terminal symbol.  If the lookahead is a non-terminal (as occurs after
 * a reduce action) then the yy_reduce_ofst[] array is used in place of
 * the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of
 * YY_SHIFT_USE_DFLT.
 *
 * The following are the tables generated in this section:
 *
 *  yy_action[]		A single table containing all actions.
 *  yy_lookahead[]	 A table containing the lookahead for each entry in
 *					 yy_action.  Used to detect hash collisions.
 *  yy_shift_ofst[]	For each state, the offset into yy_action for
 *					 shifting terminals.
 *  yy_reduce_ofst[]   For each state, the offset into yy_action for
 *					 shifting non-terminals after a reduce.
 *  yy_default[]	   Default action for each state.
 */
%%
#define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0]))

/* The next table maps tokens into fallback tokens.  If a construct
 * like the following:
 * 
 *	  %fallback ID X Y Z.
 *
 * appears in the grammer, then ID becomes a fallback token for X, Y,
 * and Z.  Whenever one of the tokens X, Y, or Z is input to the parser
 * but it does not parse, the type of the token is changed to ID and
 * the parse is retried before an error is thrown.
 */
#ifdef YYFALLBACK
static const YYCODETYPE yyFallback[] = {
%%
};
#endif /* YYFALLBACK  */

// Debug /Tracing //////////////////////////////////////////////////////////////

/* 
 * Turn parser tracing on by giving a stream to which to write the trace
 * and a prompt to preface each trace message.  Tracing is turned off
 * by making either argument NULL 
 *
 * Inputs:
 *  < ul>
 *  < li> A FILE* to which trace output should be written.
 *	  If NULL, then tracing is turned off.
 *  < li> A prefix string written at the beginning of every
 *	  line of trace output.  If NULL, then tracing is
 *	  turned off.
 *  < /ul>
 *
 * Outputs:
 * None.
 */
#ifndef NDEBUG
void %nameTrace(%nameParser* pParser, FILE *TraceFILE, const char *zTracePrompt)
{
	pParser-> yyTraceFILE = TraceFILE;
	pParser->yyTracePrompt = zTracePrompt;
	if(pParser-> yyTraceFILE == 0)
		pParser->yyTracePrompt = 0;
	else if(pParser->yyTracePrompt == 0)
		pParser-> yyTraceFILE = 0;
}

/* For tracing shifts, the names of all terminals and nonterminals
 * are required.  The following table supplies these names  */
static const char *yyTokenName[] = { 
%%
};

/* For tracing reduce actions, the names of all rules are required.
 */
static const char *yyRuleName[] = {
%%
};
#endif /* NDEBUG  */

/*
 * This function returns the symbolic name associated with a token
 * value.
 */
const char *%nameTokenName(int tokenType)
{
#ifndef NDEBUG
	if(tokenType>0 && tokenType < (sizeof(yyTokenName) / sizeof(yyTokenName[0])))
		return yyTokenName[tokenType];
	else
		return "Unknown";
#else
	return "";
#endif
}

// Shift-Reduce Stack Operations ///////////////////////////////////////////////
/*
 * Pop the parser's stack once.
 *
 * If there is a destructor routine associated with the token which
 * is popped from the stack, then call it.
 *
 * Return the major token number for the symbol popped.
 */
static int yy_pop_parser_stack(%nameParser *pParser)
{
	YYCODETYPE yymajor;
	yyStackEntry *yytos = &pParser->yystack[pParser->yyidx];
	
	if(pParser->yyidx < 0)
		return 0;
#ifndef NDEBUG
	if(pParser-> yyTraceFILE && pParser->yyidx>=0)
	{
		fprintf(pParser-> yyTraceFILE,"%sPopping %s\n", pParser->yyTracePrompt,
			yyTokenName[yytos->major]);
	}
#endif
	yymajor = yytos->major;
	yy_destructor( yymajor, &yytos->minor);
	pParser->yyidx--;
	return yymajor;
}

// Parser Operations ///////////////////////////////////////////////////////////

/* 
 * This function allocates a new parser.
 *
 * Outputs:
 * A pointer to a parser.  This pointer is used in subsequent calls
 * to Parse and ParseFree.
 */
void* %nameAlloc()
{
	%nameParser* pParser = (%nameParser*)calloc(sizeof(%nameParser)) ;
	if(pParser)
		pParser->yyidx = -1;
	return pParser;
}

/* 
 * Deallocate and destroy a parser.  Destructors are all called for
 * all stack elements before shutting the parser down. This zeroes out the
 * passed in pointer, external to the function.
 *
 * Inputs:
 *  A pointer pointer to the parser.  This should be a pointer
 *	obtained from %nameAlloc.
 */
void %nameFree(%nameParser** ppParser)
{
	if((*ppParser) == 0)
		return;

	%nameParser* pParser = *ppParser;
	*ppParser = 0;

	while(pParser->yyidx >= 0)
		yy_pop_parser_stack(pParser);
	free(pParser);
}

/* The following function deletes the value associated with a
 * symbol.  The symbol can be either a terminal or nonterminal.
 * "yymajor" is the symbol code, and "yypminor" is a pointer to
 * the value.
 */
static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){
	switch( yymajor)
	{
		/* Here is inserted the actions which take place when a
		 * terminal or non-terminal is destroyed.  This can happen
		 * when the symbol is popped from the stack during a
		 * reduce or during error processing or when a parser is 
		 * being destroyed before it is finished parsing.
		 *
		 * Note: during a reduce, the only symbols destroyed are those
		 * which appear on the RHS of the rule, but which are not used
		 * inside the C code.
		 */
%%
		default:  break;   /* If no destructor action specified: do nothing  */
	}
}

/*
 * Find the appropriate action for a parser given the terminal
 * look-ahead token iLookAhead.
 *
 * If the look-ahead token is YYNOCODE, then check to see if the action is
 * independent of the look-ahead.  If it is, return the action, otherwise
 * return YY_NO_ACTION.
 */
static int yy_find_shift_action(%nameParser *pParser, int iLookAhead)
{
	int i;
	int stateno = pParser->yystack[pParser->yyidx].stateno;
	
	i = yy_shift_ofst[stateno];
	if(i == YY_SHIFT_USE_DFLT)
		return yy_default[stateno];
	if(iLookAhead == YYNOCODE)
		return YY_NO_ACTION;

	i += iLookAhead;
	if(i < 0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead)
	{
#ifdef YYFALLBACK
		int iFallback;			/* Fallback token  */
		if(iLookAhead < sizeof(yyFallback) / sizeof(yyFallback[0]) &&
			(iFallback = yyFallback[iLookAhead])!=0)
		{
#ifndef NDEBUG
			if(pParser-> yyTraceFILE)
				fprintf(pParser-> yyTraceFILE, "%sFALLBACK %s => %s\n", pParser->yyTracePrompt,
					yyTokenName[iLookAhead], yyTokenName[iFallback]);
#endif // NDEBUG
			return yy_find_shift_action(pParser, iFallback);
		}
#endif // YYFALLBACK
		return yy_default[stateno];
	}
	else
		return yy_action[i];
}

/*
 * Find the appropriate action for a parser given the non-terminal
 * look-ahead token iLookAhead.
 *
 * If the look-ahead token is YYNOCODE, then check to see if the action is
 * independent of the look-ahead.  If it is, return the action, otherwise
 * return YY_NO_ACTION.
 */
static int yy_find_reduce_action(%nameParser *pParser, int iLookAhead)
{
	int i;
	int stateno = pParser->yystack[pParser->yyidx].stateno;
	
	i = yy_reduce_ofst[stateno];
	if(i == YY_REDUCE_USE_DFLT)
		return yy_default[stateno];
	if(iLookAhead == YYNOCODE)
		return YY_NO_ACTION;

	i += iLookAhead;
	if(i < 0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead)
		return yy_default[stateno];
	else
		return yy_action[i];
}

/*
 * Perform a shift action.
 */
static void yy_shift(%nameParser *pParser, int yyNewState, int yyMajor,				  /* The major token to shift in  */
	YYMINORTYPE *yypMinor)
{
	yyStackEntry *yytos;
	pParser->yyidx++;
	if(pParser->yyidx >= YYSTACKDEPTH)
	{
		%nameARG_FETCH;
		pParser->yyidx--;
#ifndef NDEBUG
		if(pParser-> yyTraceFILE)
			fprintf(pParser-> yyTraceFILE,"%sStack Overflow!\n",pParser->yyTracePrompt);
#endif // NDEBUG
		while( pParser->yyidx>=0)
			yy_pop_parser_stack(pParser);

		/* Here code is inserted which will execute if the parser
		 * stack ever overflows  */
%%
		%nameARG_STORE; /* Suppress warning about unused %extra_argument var  */
		return;
	}

	yytos = &pParser->yystack[pParser->yyidx];
	yytos->stateno = yyNewState;
	yytos->major = yyMajor;
	yytos->minor = *yypMinor;
#ifndef NDEBUG
	if(pParser-> yyTraceFILE && pParser->yyidx>0)
	{
		int i;
		fprintf(pParser-> yyTraceFILE, "%sShift %d\n", pParser->yyTracePrompt,yyNewState);
		fprintf(pParser-> yyTraceFILE, "%sStack:", pParser->yyTracePrompt);
		for(i = 1; i  <= pParser->yyidx; i++)
			fprintf(pParser-> yyTraceFILE," %s",yyTokenName[pParser->yystack[i].major]);
		fprintf(pParser-> yyTraceFILE,"\n");
	}
#endif // NDEBUG
}

/* The following table contains information about every rule that
 * is used during the reduce.
 */
static struct
{
  YYCODETYPE lhs;		 /* Symbol on the left-hand side of the rule  */
  unsigned char nrhs;	 /* Number of right-hand side symbols in the rule  */
} yyRuleInfo[] = {
%%
};

static void yy_accept(%nameParser*);  /* Forward Declaration  */

/*
 * Perform a reduce action and the shift that must immediately
 * follow the reduce.
 */
static void yy_reduce(%nameParser *pParser, int yyruleno)
{
	int yygoto;					 /* The next state  */
	int yyact;					  /* The next action  */
	YYMINORTYPE yygotominor;		/* The LHS of the rule reduced  */
	yyStackEntry *yymsp;			/* The top of the parser's stack  */
	int yysize;					 /* Amount to pop the stack  */
	%nameARG_FETCH;
	yymsp = &pParser->yystack[pParser->yyidx];
#ifndef NDEBUG
	if(pParser-> yyTraceFILE && yyruleno>=0 &&
		yyruleno < sizeof(yyRuleName) / sizeof(yyRuleName[0]))
		fprintf(pParser-> yyTraceFILE, "%sReduce [%s].\n", pParser->yyTracePrompt,
			yyRuleName[yyruleno]);
#endif /* NDEBUG  */

	switch( yyruleno)
	{
		/* Beginning here are the reduction cases.  A typical example
		 * follows:
		 *   case 0:
		 *  #line  < lineno>  < grammarfile>
		 *	 { ... }		   // User supplied code
		 *  #line  < lineno>  < thisfile>
		 *	 break;
		 */
%%
	};
	yygoto = yyRuleInfo[yyruleno].lhs;
	yysize = yyRuleInfo[yyruleno].nrhs;
	pParser->yyidx -= yysize;
	yyact = yy_find_reduce_action(pParser,yygoto);
	if(yyact  <  YYNSTATE)
		yy_shift(pParser,yyact,yygoto,&yygotominor);
	else if(yyact  ==  YYNSTATE + YYNRULE + 1)
		yy_accept(pParser);
}

/*
 * The following code executes when the parse fails
 */
static void yy_parse_failed(%nameParser *pParser)
{
	%nameARG_FETCH;
#ifndef NDEBUG
	if(pParser-> yyTraceFILE)
		fprintf(pParser-> yyTraceFILE,"%sFail!\n",pParser->yyTracePrompt);
#endif // NDEBUG
	while( pParser->yyidx>=0)
		yy_pop_parser_stack(pParser);
	/* Here code is inserted which will be executed whenever the
	 * parser fails  */
%%
	%nameARG_STORE; /* Suppress warning about unused %extra_argument variable  */
}

/*
 * The following code executes when a syntax error first occurs.
 */
static void yy_syntax_error(%nameParser *pParser, int yymajor,
	YYMINORTYPE yyminor)
{
	%nameARG_FETCH;
#define TOKEN (yyminor.yy0)
%%
	%nameARG_STORE; /* Suppress warning about unused %extra_argument variable  */
}

/*
 * The following is executed when the parser accepts
 */
static void yy_accept(%nameParser *pParser)
{
	%nameARG_FETCH;
#ifndef NDEBUG
	if(pParser-> yyTraceFILE)
		fprintf(pParser-> yyTraceFILE,"%sAccept!\n",pParser->yyTracePrompt);
#endif // NDEBUG
	while( pParser->yyidx>=0)
		yy_pop_parser_stack(pParser);
	/* Here code is inserted which will be executed whenever the
	 * parser accepts  */
%%
	%nameARG_STORE; /* Suppress warning about unused %extra_argument variable  */
}

/* The main parser program.
 * The first argument is a pointer to a structure obtained from
 * "%nameAlloc" which describes the current state of the parser.
 * The second argument is the major token number.  The third is
 * the minor token.  The fourth optional argument is whatever the
 * user wants (and specified in the grammar) and is available for
 * use by the action routines.
 *
 * Inputs:
 *  < ul>
 *  < li> A pointer to the parser.
 *  < li> The major token number.
 *  < li> The minor token number.
 *  < li> An option argument of a grammar-specified type.
 *  < /ul>
 */
void %nameParse(%nameParser* pParser, int yymajor, %nameTOKENTYPE yyminor %nameARG_PDECL)
{
	YYMINORTYPE yyminorunion;
	int yyact;			/* The parser action.  */
	int yyendofinput;	 /* True if we are at the end of input  */
	int yyerrorhit = 0;   /* True if yymajor has invoked an error  */
	%nameParser *pParser;  /* The parser  */

	/* (re)initialize the parser, if necessary  */
	if(pParser->yyidx < 0)
	{
		if(yymajor == 0)
			return;
		pParser->yyidx = 0;
		pParser->yyerrcnt = -1;
		pParser->yystack[0].stateno = 0;
		pParser->yystack[0].major = 0;
	}
	yyminorunion.yy0 = yyminor;
	yyendofinput = (yymajor == 0);
	%nameARG_STORE;

#ifndef NDEBUG
	if(pParser-> yyTraceFILE)
		fprintf(pParser-> yyTraceFILE,"%sInput %s\n",pParser->yyTracePrompt, yyTokenName[yymajor]);
#endif // NDEBUG

	do
	{
		yyact = yy_find_shift_action(pParser,yymajor);
		if(yyact < YYNSTATE)
		{
			yy_shift(pParser,yyact,yymajor,&yyminorunion);
			pParser->yyerrcnt--;
			if(yyendofinput && pParser->yyidx>=0)
			{
				yymajor = 0;
			}
			else
			{
				yymajor = YYNOCODE;
			}
		}
		else if(yyact  <  YYNSTATE + YYNRULE)
		{
			yy_reduce(pParser,yyact-YYNSTATE);
		}
		else if(yyact  ==  YY_ERROR_ACTION)
		{
#ifndef NDEBUG
			if(pParser-> yyTraceFILE)
			{
				fprintf(pParser-> yyTraceFILE,"%sSyntax Error!\n",pParser->yyTracePrompt);
			}
#endif
#ifdef YYERRORSYMBOL
			/* A syntax error has occurred.
			 * The response to an error depends upon whether or not the
			 * grammar defines an error token "ERROR".  
			 *
			 * This is what we do if the grammar does define ERROR:
			 *
			 *  * Call the %syntax_error function.
			 *
			 *  * Begin popping the stack until we enter a state where
			 *	it is legal to shift the error symbol, then shift
			 *	the error symbol.
			 *
			 *  * Set the error count to three.
			 *
			 *  * Begin accepting and shifting new tokens.  No new error
			 *	processing will occur until three tokens have been
			 *	shifted successfully.
			 *
			 */
			if(pParser->yyerrcnt < 0)
			{
				yy_syntax_error(pParser,yymajor,yyminorunion);
			}
			pParser->yyerrcnt = 3;
			yyerrorhit = 1;

			int tos = pParser->yystack[pParser->yyidx].major;
			if(tos == YYERRORSYMBOL || yyerrorhit)
			{
#ifndef NDEBUG
				if(pParser-> yyTraceFILE)
				{
					fprintf(pParser-> yyTraceFILE, "%sDiscard input token %s\n",
						pParser->yyTracePrompt, yyTokenName[yymajor]);
				}
#endif // NDEBUG
				yy_destructor(yymajor,&yyminorunion);
				yymajor = YYNOCODE;
			}
			else
			{
				yyact = yy_find_shift_action(pParser, YYERRORSYMBOL);
				while(pParser->yyidx >= 0 && (yyact >= YYNSTATE)
				{
					yy_pop_parser_stack(pParser);
					yyact = yy_find_shift_action(pParser, YYERRORSYMBOL);
				}

				if(pParser->yyidx < 0 || yymajor == 0)
				{
					yy_destructor(yymajor,&yyminorunion);
					yy_parse_failed(pParser);
					yymajor = YYNOCODE;
				}
				else if(tos != YYERRORSYMBOL)
				{
					YYMINORTYPE u2;
					u2.YYERRSYMDT = 0;
					yy_shift(pParser,yyact,YYERRORSYMBOL,&u2);
				}
			}
#else // YYERRORSYMBOL is not defined
			/* This is what we do if the grammar does not define ERROR:
			 *
			 *  * Report an error message, and throw away the input token.
			 *
			 *  * If the input token is $, then fail the parse.
			 *
			 * As before, subsequent error messages are suppressed until
			 * three input tokens have been successfully shifted.
			 */
			if(pParser->yyerrcnt < =0)
			{
				yy_syntax_error(pParser,yymajor,yyminorunion);
			}
			pParser->yyerrcnt = 3;
			yy_destructor(yymajor,&yyminorunion);
			if(yyendofinput)
			{
				yy_parse_failed(pParser);
			}
			yymajor = YYNOCODE;
#endif // YYERRORSYMBOL
		}
		else
		{
			yy_accept(pParser);
			yymajor = YYNOCODE;
		}
	} while(yymajor != YYNOCODE && pParser->yyidx >= 0);
}
